package GM.diagram.providers;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;

import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.edit.ui.provider.AdapterFactoryLabelProvider;
import org.eclipse.gmf.runtime.diagram.ui.editparts.IGraphicalEditPart;
import org.eclipse.gmf.runtime.emf.type.core.ElementTypeRegistry;
import org.eclipse.gmf.runtime.emf.type.core.IElementType;
import org.eclipse.gmf.runtime.emf.ui.services.modelingassistant.ModelingAssistantProvider;
import org.eclipse.gmf.runtime.notation.Diagram;
import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.jface.window.Window;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.dialogs.ElementListSelectionDialog;

import GM.diagram.edit.parts.ActionEditPart;
import GM.diagram.edit.parts.AdGoalEditPart;
import GM.diagram.edit.parts.AgentEditPart;
import GM.diagram.edit.parts.Definition2EditPart;
import GM.diagram.edit.parts.Definition3EditPart;
import GM.diagram.edit.parts.Definition4EditPart;
import GM.diagram.edit.parts.Definition5EditPart;
import GM.diagram.edit.parts.Definition6EditPart;
import GM.diagram.edit.parts.Definition7EditPart;
import GM.diagram.edit.parts.Definition8EditPart;
import GM.diagram.edit.parts.DefinitionEditPart;
import GM.diagram.edit.parts.EntityEditPart;
import GM.diagram.edit.parts.EventEditPart;
import GM.diagram.edit.parts.GoalDiagramEditPart;
import GM.diagram.edit.parts.GoalEditPart;
import GM.diagram.edit.parts.OperationEditPart;
import GM.diagram.edit.parts.Reference2EditPart;
import GM.diagram.edit.parts.ReferenceEditPart;
import GM.diagram.edit.parts.RefinementLinkEditPart;
import GM.diagram.part.GMDiagramEditorPlugin;
import GM.diagram.part.Messages;

/**
 * @generated
 */
public class GMModelingAssistantProvider extends ModelingAssistantProvider {

	/**
	 * @generated
	 */
	public List getTypesForPopupBar(IAdaptable host) {
		IGraphicalEditPart editPart = (IGraphicalEditPart) host
				.getAdapter(IGraphicalEditPart.class);
		if (editPart instanceof GoalDiagramEditPart) {
			ArrayList<IElementType> types = new ArrayList<IElementType>(8);
			types.add(GMElementTypes.Goal_2001);
			types.add(GMElementTypes.AdGoal_2002);
			types.add(GMElementTypes.Operation_2003);
			types.add(GMElementTypes.Entity_2004);
			types.add(GMElementTypes.Event_2005);
			types.add(GMElementTypes.Action_2006);
			types.add(GMElementTypes.Agent_2007);
			types.add(GMElementTypes.RefinementLink_2008);
			return types;
		}
		if (editPart instanceof GoalEditPart) {
			ArrayList<IElementType> types = new ArrayList<IElementType>(1);
			types.add(GMElementTypes.Definition_3031);
			return types;
		}
		if (editPart instanceof AdGoalEditPart) {
			ArrayList<IElementType> types = new ArrayList<IElementType>(2);
			types.add(GMElementTypes.Definition_3033);
			types.add(GMElementTypes.Definition_3032);
			return types;
		}
		if (editPart instanceof OperationEditPart) {
			ArrayList<IElementType> types = new ArrayList<IElementType>(5);
			types.add(GMElementTypes.Definition_3034);
			types.add(GMElementTypes.Definition_3035);
			types.add(GMElementTypes.Definition_3038);
			types.add(GMElementTypes.Definition_3036);
			types.add(GMElementTypes.Definition_3037);
			return types;
		}
		if (editPart instanceof EntityEditPart) {
			ArrayList<IElementType> types = new ArrayList<IElementType>(3);
			types.add(GMElementTypes.State_3041);
			types.add(GMElementTypes.Attribute_3039);
			types.add(GMElementTypes.Reference_3040);
			return types;
		}
		if (editPart instanceof EventEditPart) {
			ArrayList<IElementType> types = new ArrayList<IElementType>(2);
			types.add(GMElementTypes.Attribute_3042);
			types.add(GMElementTypes.Reference_3043);
			return types;
		}
		if (editPart instanceof DefinitionEditPart) {
			ArrayList<IElementType> types = new ArrayList<IElementType>(1);
			types.add(GMElementTypes.Mapping_3044);
			return types;
		}
		if (editPart instanceof Definition2EditPart) {
			ArrayList<IElementType> types = new ArrayList<IElementType>(1);
			types.add(GMElementTypes.Mapping_3045);
			return types;
		}
		if (editPart instanceof Definition3EditPart) {
			ArrayList<IElementType> types = new ArrayList<IElementType>(1);
			types.add(GMElementTypes.Mapping_3046);
			return types;
		}
		if (editPart instanceof Definition4EditPart) {
			ArrayList<IElementType> types = new ArrayList<IElementType>(1);
			types.add(GMElementTypes.Mapping_3047);
			return types;
		}
		if (editPart instanceof Definition5EditPart) {
			ArrayList<IElementType> types = new ArrayList<IElementType>(1);
			types.add(GMElementTypes.Mapping_3048);
			return types;
		}
		if (editPart instanceof Definition6EditPart) {
			ArrayList<IElementType> types = new ArrayList<IElementType>(1);
			types.add(GMElementTypes.Mapping_3049);
			return types;
		}
		if (editPart instanceof Definition7EditPart) {
			ArrayList<IElementType> types = new ArrayList<IElementType>(1);
			types.add(GMElementTypes.Mapping_3050);
			return types;
		}
		if (editPart instanceof Definition8EditPart) {
			ArrayList<IElementType> types = new ArrayList<IElementType>(1);
			types.add(GMElementTypes.Mapping_3051);
			return types;
		}
		return Collections.EMPTY_LIST;
	}

	/**
	 * @generated
	 */
	public List getRelTypesOnSource(IAdaptable source) {
		IGraphicalEditPart sourceEditPart = (IGraphicalEditPart) source
				.getAdapter(IGraphicalEditPart.class);
		if (sourceEditPart instanceof GoalEditPart) {
			return ((GoalEditPart) sourceEditPart).getMARelTypesOnSource();
		}
		if (sourceEditPart instanceof AdGoalEditPart) {
			return ((AdGoalEditPart) sourceEditPart).getMARelTypesOnSource();
		}
		if (sourceEditPart instanceof AgentEditPart) {
			return ((AgentEditPart) sourceEditPart).getMARelTypesOnSource();
		}
		if (sourceEditPart instanceof RefinementLinkEditPart) {
			return ((RefinementLinkEditPart) sourceEditPart)
					.getMARelTypesOnSource();
		}
		if (sourceEditPart instanceof ReferenceEditPart) {
			return ((ReferenceEditPart) sourceEditPart).getMARelTypesOnSource();
		}
		if (sourceEditPart instanceof Reference2EditPart) {
			return ((Reference2EditPart) sourceEditPart)
					.getMARelTypesOnSource();
		}
		return Collections.EMPTY_LIST;
	}

	/**
	 * @generated
	 */
	public List getRelTypesOnTarget(IAdaptable target) {
		IGraphicalEditPart targetEditPart = (IGraphicalEditPart) target
				.getAdapter(IGraphicalEditPart.class);
		if (targetEditPart instanceof GoalEditPart) {
			return ((GoalEditPart) targetEditPart).getMARelTypesOnTarget();
		}
		if (targetEditPart instanceof OperationEditPart) {
			return ((OperationEditPart) targetEditPart).getMARelTypesOnTarget();
		}
		if (targetEditPart instanceof EntityEditPart) {
			return ((EntityEditPart) targetEditPart).getMARelTypesOnTarget();
		}
		if (targetEditPart instanceof ActionEditPart) {
			return ((ActionEditPart) targetEditPart).getMARelTypesOnTarget();
		}
		if (targetEditPart instanceof RefinementLinkEditPart) {
			return ((RefinementLinkEditPart) targetEditPart)
					.getMARelTypesOnTarget();
		}
		return Collections.EMPTY_LIST;
	}

	/**
	 * @generated
	 */
	public List getRelTypesOnSourceAndTarget(IAdaptable source,
			IAdaptable target) {
		IGraphicalEditPart sourceEditPart = (IGraphicalEditPart) source
				.getAdapter(IGraphicalEditPart.class);
		IGraphicalEditPart targetEditPart = (IGraphicalEditPart) target
				.getAdapter(IGraphicalEditPart.class);
		if (sourceEditPart instanceof GoalEditPart) {
			return ((GoalEditPart) sourceEditPart)
					.getMARelTypesOnSourceAndTarget(targetEditPart);
		}
		if (sourceEditPart instanceof AdGoalEditPart) {
			return ((AdGoalEditPart) sourceEditPart)
					.getMARelTypesOnSourceAndTarget(targetEditPart);
		}
		if (sourceEditPart instanceof AgentEditPart) {
			return ((AgentEditPart) sourceEditPart)
					.getMARelTypesOnSourceAndTarget(targetEditPart);
		}
		if (sourceEditPart instanceof RefinementLinkEditPart) {
			return ((RefinementLinkEditPart) sourceEditPart)
					.getMARelTypesOnSourceAndTarget(targetEditPart);
		}
		if (sourceEditPart instanceof ReferenceEditPart) {
			return ((ReferenceEditPart) sourceEditPart)
					.getMARelTypesOnSourceAndTarget(targetEditPart);
		}
		if (sourceEditPart instanceof Reference2EditPart) {
			return ((Reference2EditPart) sourceEditPart)
					.getMARelTypesOnSourceAndTarget(targetEditPart);
		}
		return Collections.EMPTY_LIST;
	}

	/**
	 * @generated
	 */
	public List getTypesForSource(IAdaptable target,
			IElementType relationshipType) {
		IGraphicalEditPart targetEditPart = (IGraphicalEditPart) target
				.getAdapter(IGraphicalEditPart.class);
		if (targetEditPart instanceof GoalEditPart) {
			return ((GoalEditPart) targetEditPart)
					.getMATypesForSource(relationshipType);
		}
		if (targetEditPart instanceof OperationEditPart) {
			return ((OperationEditPart) targetEditPart)
					.getMATypesForSource(relationshipType);
		}
		if (targetEditPart instanceof EntityEditPart) {
			return ((EntityEditPart) targetEditPart)
					.getMATypesForSource(relationshipType);
		}
		if (targetEditPart instanceof ActionEditPart) {
			return ((ActionEditPart) targetEditPart)
					.getMATypesForSource(relationshipType);
		}
		if (targetEditPart instanceof RefinementLinkEditPart) {
			return ((RefinementLinkEditPart) targetEditPart)
					.getMATypesForSource(relationshipType);
		}
		return Collections.EMPTY_LIST;
	}

	/**
	 * @generated
	 */
	public List getTypesForTarget(IAdaptable source,
			IElementType relationshipType) {
		IGraphicalEditPart sourceEditPart = (IGraphicalEditPart) source
				.getAdapter(IGraphicalEditPart.class);
		if (sourceEditPart instanceof GoalEditPart) {
			return ((GoalEditPart) sourceEditPart)
					.getMATypesForTarget(relationshipType);
		}
		if (sourceEditPart instanceof AdGoalEditPart) {
			return ((AdGoalEditPart) sourceEditPart)
					.getMATypesForTarget(relationshipType);
		}
		if (sourceEditPart instanceof AgentEditPart) {
			return ((AgentEditPart) sourceEditPart)
					.getMATypesForTarget(relationshipType);
		}
		if (sourceEditPart instanceof RefinementLinkEditPart) {
			return ((RefinementLinkEditPart) sourceEditPart)
					.getMATypesForTarget(relationshipType);
		}
		if (sourceEditPart instanceof ReferenceEditPart) {
			return ((ReferenceEditPart) sourceEditPart)
					.getMATypesForTarget(relationshipType);
		}
		if (sourceEditPart instanceof Reference2EditPart) {
			return ((Reference2EditPart) sourceEditPart)
					.getMATypesForTarget(relationshipType);
		}
		return Collections.EMPTY_LIST;
	}

	/**
	 * @generated
	 */
	public EObject selectExistingElementForSource(IAdaptable target,
			IElementType relationshipType) {
		return selectExistingElement(target,
				getTypesForSource(target, relationshipType));
	}

	/**
	 * @generated
	 */
	public EObject selectExistingElementForTarget(IAdaptable source,
			IElementType relationshipType) {
		return selectExistingElement(source,
				getTypesForTarget(source, relationshipType));
	}

	/**
	 * @generated
	 */
	protected EObject selectExistingElement(IAdaptable host, Collection types) {
		if (types.isEmpty()) {
			return null;
		}
		IGraphicalEditPart editPart = (IGraphicalEditPart) host
				.getAdapter(IGraphicalEditPart.class);
		if (editPart == null) {
			return null;
		}
		Diagram diagram = (Diagram) editPart.getRoot().getContents().getModel();
		HashSet<EObject> elements = new HashSet<EObject>();
		for (Iterator<EObject> it = diagram.getElement().eAllContents(); it
				.hasNext();) {
			EObject element = it.next();
			if (isApplicableElement(element, types)) {
				elements.add(element);
			}
		}
		if (elements.isEmpty()) {
			return null;
		}
		return selectElement((EObject[]) elements.toArray(new EObject[elements
				.size()]));
	}

	/**
	 * @generated
	 */
	protected boolean isApplicableElement(EObject element, Collection types) {
		IElementType type = ElementTypeRegistry.getInstance().getElementType(
				element);
		return types.contains(type);
	}

	/**
	 * @generated
	 */
	protected EObject selectElement(EObject[] elements) {
		Shell shell = Display.getCurrent().getActiveShell();
		ILabelProvider labelProvider = new AdapterFactoryLabelProvider(
				GMDiagramEditorPlugin.getInstance()
						.getItemProvidersAdapterFactory());
		ElementListSelectionDialog dialog = new ElementListSelectionDialog(
				shell, labelProvider);
		dialog.setMessage(Messages.GMModelingAssistantProviderMessage);
		dialog.setTitle(Messages.GMModelingAssistantProviderTitle);
		dialog.setMultipleSelection(false);
		dialog.setElements(elements);
		EObject selected = null;
		if (dialog.open() == Window.OK) {
			selected = (EObject) dialog.getFirstResult();
		}
		return selected;
	}
}
